package Simcomp::Result;
use warnings;
use strict;
use lib qw( ../ );
use Simcomp::Process;
use Carp qw(croak);

sub new
{
	my $class = shift;
	ref( $class ) and croak( "Este mtodo deve ser chamado a partir de
		uma referncia a uma classe." );
	my %attributes;
	bless \%attributes, $class;
	my $self = \%attributes;
	$self->{'list'} = [()];
	$self->{'cpu_data'} = [()];;
	$self->{'DISK_A'}->{'disk_data'} = [()];;
	$self->{'DISK_B'}->{'disk_data'} = [()];;
	$self->{'cpu_state'} = [()];;
	$self->{'DISK_A'}->{'disk_status'} = [()];;
	$self->{'DISK_B'}->{'disk_status'} = [()];;
	return $self;
}

sub add_cpu_state
{
	my $self = shift;
	my %cpu_state = ( cpu_state => shift, event_time => shift );
	
	push @{$self->{'cpu_state'}}, \%cpu_state;
	
}

sub cpu_state
{
	$_[0]->{'cpu_state'};
}

sub cpu_idle_percentage
{
	my $self = shift;
	my $ant_time = 0;
	my $accumulator = 0;
	my $total_time = 0;
	for my $cpu_hash ( @{$self->cpu_state} )
	{
		my $time_interv = $cpu_hash->{'event_time'} - $ant_time;
		if ($cpu_hash->{'cpu_state'} eq 'idle')
		{
			$accumulator += $time_interv;
		}
		$total_time += $time_interv;
		$ant_time = $cpu_hash->{'event_time'};
	}

	if ( $total_time )
	{
	    $accumulator / $total_time;
	}
	else
	{
	    0;
	}
	
}

sub cpu_overhead_percentage
{
	my $self = shift;
	my $ant_time = 0;
	my $accumulator = 0;
	my $total_time = 0;
	for my $cpu_hash ( @{$self->cpu_state} )
	{
		my $time_interv = $cpu_hash->{'event_time'} - $ant_time;
		if ($cpu_hash->{'cpu_state'} eq 'overhead')
		{
			$accumulator += $time_interv;
		}
		$total_time += $time_interv;
		$ant_time = $cpu_hash->{'event_time'};
	}

	if ( $total_time )
	{
	    $accumulator / $total_time;
	}
	else
	{
	    0;
	}
	
}

sub cpu_processing_percentage
{
	my $self = shift;
	my $ant_time = 0;
	my $accumulator = 0;
	my $total_time = 0;
	for my $cpu_hash ( @{$self->cpu_state} )
	{
		my $time_interv = $cpu_hash->{'event_time'} - $ant_time;
		if ($cpu_hash->{'cpu_state'} eq 'processing')
		{
			$accumulator += $time_interv;
		}
		$total_time += $time_interv;
		$ant_time = $cpu_hash->{'event_time'};
	}

	if ( $total_time )
	{
	    $accumulator / $total_time;
	}
	else
	{
	    0;
	}
	
}


sub add_diskA_state
{
	my $self = shift;
	my %diskA_state = ( disk_state => shift, event_time => shift );
	
	push @{$self->{'DISK_A'}->{'disk_status'}}, \%diskA_state;
	
}

sub diskA_state
{
	$_[0]->{'DISK_A'}->{'diskA_state'};
}

sub add_diskB_state
{
	my $self = shift;
	my %diskB_state = ( disk_state => shift, event_time => shift );
	
	push @{$self->{'DISK_B'}->{'disk_status'}}, \%diskB_state;
	
}

sub diskB_state
{
	$_[0]->{'DISK_B'}->{'diskB_state'};
}

sub disk_idle_percentage
{
	my $self = shift;
	my $disk = shift;
	my $ant_time = 0;
	my $accumulator = 0;
	my $total_time = 0;
	
	for my $disk_hash( @{$self->{$disk}->{'disk_status'} } )
	{
		my $time_interv = $disk_hash->{'event_time'} - $ant_time;
		if ($disk_hash->{'disk_state'} eq 'idle')
		{
			$accumulator += $time_interv;
		}
		$total_time += $time_interv;
		$ant_time = $disk_hash->{'event_time' };
	}
	
	if ( $total_time )
	{
	    $accumulator  / $total_time;
	}
	else
	{
	    0;
	}
	
}

sub add_queue_size_in_cpu
{
	my $self = shift;
	my %cpu_data = ( queue_size => shift, event_time => shift );
	
	push @{$self->{'cpu_data'}}, \%cpu_data;
	
}

sub cpu_data
{
	$_[0]->{'cpu_data'};
}

sub add_queue_size_in_disk_A
{
	my $self = shift;
	my %disk_data = ( queue_size => shift, event_time => shift );
	
	push @{$self->{'DISK_A'}->{'disk_data'}}, \%disk_data;	
}

sub add_queue_size_in_disk_B
{
	my $self = shift;
	my %disk_data = ( queue_size => shift, event_time => shift );
	
	push @{$self->{'DISK_B'}->{'disk_data'}}, \%disk_data;
}

sub disk_A_data
{
	$_[0]->{'DISK_A'}->{'disk_data'};
}

sub disk_B_data
{
	$_[0]->{'DISK_B'}->{'disk_data'};
}


sub process_list
{
	return $_[0]->{'list'};
}

sub add_process
{
	my $self = shift;
	push @{ $self->process_list }, shift;
	
	
}

sub get_statistics
{
	my $self = shift;
	my %st;
		
	my $diskA_counter = 0;
	my $diskB_counter = 0;

	$st{'time_in_disk_A_queue'} = 0;
	$st{'time_in_disk_B_queue'} = 0;

	for my $process ( @{$self->process_list})
	{
		$st{'total_time'} += $process->total_time;
		$st{'time_in_cpu_queue'} += $process->time_in_cpu_queue;
		
		if ( $process->disk eq "DISK_A" )
		{
			$st{'time_in_disk_A_queue'} += $process->time_in_disk_queue;
			$diskA_counter++;
		}
		elsif ( $process->disk eq "DISK_B")
		{
			$st{'time_in_disk_B_queue'} += $process->time_in_disk_queue;
			$diskB_counter++;
		}
			
	}
	
	$st{'total_time'} /= scalar @{$self->process_list};
	$st{'time_in_cpu_queue'} /= scalar @{ $self->process_list };
	$st{'time_in_disk_A_queue'} /= $diskA_counter if ( $diskA_counter );
	$st{'time_in_disk_B_queue'} /= $diskB_counter if ( $diskB_counter );
	$st{'cpu_media_queue_size'} = $self->cpu_media_queue_size;
	$st{'diskA_media_queue_size'} = $self->disk_media_queue_size( "DISK_A" );
	$st{'diskB_media_queue_size'} = $self->disk_media_queue_size( "DISK_B" );
	$st{'cpu_idle_percentage'} = $self->cpu_idle_percentage;
	$st{'cpu_overhead_percentage'} = $self->cpu_overhead_percentage;
	$st{'cpu_processing_percentage'} = $self->cpu_processing_percentage;
	$st{'diskA_idle_percentage'} = $self->disk_idle_percentage( "DISK_A" );
	$st{'diskB_idle_percentage'} = $self->disk_idle_percentage( "DISK_B" );
	return %st;
	 	
}

sub cpu_media_queue_size
{
	my $self = shift;
	my $ant_time = 0;
	my $accumulator = 0;
	
	for my $cpu_hash ( @{$self->cpu_data} )
	{
		my $time_interv = $cpu_hash->{'event_time'} - $ant_time;
		$accumulator += $cpu_hash->{'queue_size'} * $time_interv;
		$ant_time = $cpu_hash->{'event_time'};
	}

	if ( $ant_time )
	{
	    $accumulator / $ant_time;
	}
	else
	{
	    0;
	}
	
}

sub disk_media_queue_size
{
	my $self = shift;
	my $disk = shift;
	my $ant_time = 0;
	my $accumulator;
	
	for my $disk_hash( @{$self->{$disk}->{'disk_data'} } )
	{
		my $time_interv = $disk_hash->{'event_time'} - $ant_time;
		$accumulator += $disk_hash->{'queue_size'} * $time_interv;
		$ant_time = $disk_hash->{'event_time' };
	}
	
	if ( $ant_time )
	{
	    $accumulator  / $ant_time;
	}
	else
	{
	    0;
	}
	
}

1;
